using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Needle.Core;
using Needle.Framework;

namespace Needle.Utils
{

    /// <summary>
    /// Ensures conditions are true, by throwing an (argument) exception if they're not.
    /// </summary>
    [DebuggerNonUserCode]
    public static class Ensure
    {

       /// <summary>
        /// Throws an InvalidOperationException if isValid is false. 
        /// </summary>
        public static void ValidOperation(bool isValid, string message)
        {
            if (!isValid)
                throw new InvalidOperationException(message);
        }

        /// <summary>
        /// Throw if the the id is null, or a DepenencyId.Null
        /// </summary>
        public static void NotNull(InstanceId id, string argName)
        {
            if (id == null || id.IsNull)
                throw new ArgumentException( argName + " is null", argName);
        }
        /// <summary>
        /// Throw if the object is not of type T.
        /// </summary>
        public static void Is<T>(object o, string argName, string message)
        {
            if (!(o is T))
                throw new ArgumentException(message, argName);
        }

        /// <summary>
        /// Throw if the object has been disposed.
        /// </summary>
        public static void NotDisposed(INotifyDisposed obj)
        {
            if (obj.IsDisposed)
                throw new ObjectDisposedException(obj.ToString());
        }
        /// <summary>
        /// Throw if the string is null or empty.
        /// </summary>
        public static void NotNullOrEmpty(string arg, string argName)
        {
            if (String.IsNullOrEmpty(arg))
                NotNullOrEmpty(arg, argName, argName + " is null or empty");
        }

        /// <summary>
        /// Throw if the string is null or empty.
        /// </summary>
        public static void NotNullOrEmpty(string arg, string argName, string message)
        {
            if (String.IsNullOrEmpty(arg))
                throw new ArgumentException(message, argName);
        }

        /// <summary>
        /// Throw if the array is null or empty.
        /// </summary>
        public static void NotNullOrEmpty(Array arg, string argName)
        {
            if (arg == null || arg.Length == 0)
                throw new ArgumentException(argName + " is null or empty", argName);
        }

        /// <summary>
        /// Throw if the array is null or empty.
        /// </summary>
        public static void NotNullOrEmpty(Array arg, string argName, string message)
        {
            if (arg == null || arg.Length == 0)
                throw new ArgumentException(message, argName);
        }

        /// <summary>
        /// Throw if the list is null or empty.
        /// </summary>
        public static void NotNullOrEmpty<T>(IList<T> arg, string argName)
        {
            if (arg == null || arg.Count == 0)
                throw new ArgumentException(argName + " is null or empty", argName);
        }

        /// <summary>
        /// Throw if the list is null or empty.
        /// </summary>
        public static void NotNullOrEmpty<T>(IList<T> arg, string argName, string message)
        {
            if (arg == null || arg.Count == 0)
                throw new ArgumentException(message, argName);
        }

        /// <summary>
        /// Throw if the object is null.
        /// </summary>
        public static void NotNull(object arg, string argName)
        {
            if (arg == null)
                NotNull(arg, argName, argName + " is null");
        }

        /// <summary>
        /// Throw if the object is not null.
        /// </summary>
        public static void IsNull(object arg, string message)
        {
            if (arg != null)
                throw new ArgumentException(message);
        }

        /// <summary>
        /// Throw if the object is not null.
        /// </summary>
        public static void NotNull(object arg, string argName, string message)
        {
            if (arg == null)
                throw new ArgumentNullException(argName, message);
        }
        /// <summary>
        /// Throw if the condition is false.
        /// </summary>
        public static void IsTrue(bool condition, string argName, string message)
        {
            IsFalse(!condition, argName, message);
        }

        /// <summary>
        /// Throw if the condition is true.
        /// </summary>
        public static void IsFalse(bool condition, string argName, string message)
        {
            if (condition)
                throw new ArgumentException(argName, message);
        }

        /// <summary>
        /// Throw if the strings are equal.
        /// </summary>
        public static void NotEqual(string actual, string reference, string argName)
        {
            NotEqual(actual, reference, StringComparison.CurrentCulture, argName);
        }

        /// <summary>
        /// Throw if the string are equal.
        /// </summary>
        public static void NotEqual(string actual, string reference, StringComparison comparison, string argName)
        {
            if (String.Equals(actual, reference, comparison))
                throw new ArgumentException("Duplicate " + argName, argName);
        }

        /// <summary>
        /// Throw if the index is not valid.
        /// </summary>
        public static void IndexValid(int index, IList list, string argName)
        {
            if (index < 0 || index >= list.Count)
                throw new ArgumentOutOfRangeException(argName, "The value " + index + " for " + argName + " is out of range.");
        }

        /// <summary>
        /// Throw if the value is smaller or equal to p.
        /// </summary>
        public static void GreaterThan(int p, int value, string argName)
        {
            if (value <= p)
                throw new ArgumentOutOfRangeException(argName, String.Format("{0} must be greater than {1}", argName, p));
        }
        /// <summary>
        /// Throw if the value is greater or equal to p.
        /// </summary>
        public static void SmallerThan(int p, int value, string argName)
        {
            if (value >= p)
                throw new ArgumentOutOfRangeException(argName, String.Format("{0} must be smaller than {1}", argName, p));
        }

        /// <summary>
        /// throw if the guid is empty
        /// </summary>
        public static void NotEmpty(Guid id, string argName)
        {
            if (id == Guid.Empty)
                throw new ArgumentException(argName + " is empty.", argName);
        }
    }
}
